<template>
  <PageContainer>
    <view class="container">
      <Header :title="headerTitle" />
      <view
        class="TUIChat"
        :style="'height:calc(100vh - ' + (headerHeight + keyboardHeight) + 'px);'"
        v-if="conversationType === 'chat'"
      >
        <view class="more-btn" v-if="conversation?.type === 'GROUP'" @click="handleGetProfile">
          更多
        </view>
        <view class="TUIChat-container">
          <scroll-view
            class="TUIChat-main"
            :scroll-y="scrollY"
            :scroll-with-animation="true"
            :refresher-triggered="triggered"
            :refresher-enabled="true"
            @refresherrefresh="handleRefresher"
            :scroll-top="scrollTop"
            @scroll="handleScroll"
          >
            <view class="TUI-message-list" @touchstart="handleTouchStart">
              <view v-for="(item, index) in messages" :key="item.ID" :id="'view' + item.ID">
                <view class="time-container" v-if="item.showTime">
                  {{ caculateTimeago(item.time * 1000) }}
                </view>
                <MessageTip
                  v-if="!item.isRevoked && item.type === types.MSG_GRP_TIP"
                  :data="handleTipMessageShowContext(item)"
                />
                <!-- <MessageTip v-if="item.type === types.MSG_GRP_SYS_NOTICE" /> -->
                <MessageBubble
                  v-if="!item.isRevoked && item.type !== types.MSG_GRP_TIP"
                  :data="item"
                >
                  <MessageText
                    :id="item.flow + '-' + item.ID"
                    v-if="item.type === types.MSG_TEXT"
                    :data="handleTextMessageShowContext(item)"
                    :messageData="item"
                  ></MessageText>
                  <MessageImage
                    :id="item.flow + '-' + item.ID"
                    v-if="item.type === types.MSG_IMAGE"
                    :data="handleImageMessageShowContext(item)"
                    :messageData="item"
                  ></MessageImage>
                  <MessageVideo
                    :id="item.flow + '-' + item.ID"
                    v-if="item.type === types.MSG_VIDEO"
                    :data="handleVideoMessageShowContext(item)"
                    :messageData="item"
                  />
                  <MessageAudio
                    :id="item.flow + '-' + item.ID"
                    v-if="item.type === types.MSG_AUDIO"
                    :data="handleAudioMessageShowContext(item)"
                    :messageData="item"
                  />
                  <MessageFace
                    :id="item.flow + '-' + item.ID"
                    v-if="item.type === types.MSG_FACE"
                    :data="handleFaceMessageShowContext(item)"
                    :messageData="item"
                  />
                  <MessageCustom
                    :id="item.flow + '-' + item.ID"
                    v-if="item.type === types.MSG_CUSTOM"
                    :data="handleCustomMessageShowContext(item)"
                    :messageData="item"
                  />
                </MessageBubble>
                <MessageRevoked v-if="item.isRevoked" :data="item" @edit="handleEdit(item)" />
              </view>
            </view>
          </scroll-view>
        </view>
        <TUIChatInput
          :text="text"
          :conversationData="conversation"
          @focus="handleScrollBottom"
          @blur="inputBlur"
        ></TUIChatInput>
      </view>
      <view
        class="TUIChat"
        :style="'height:calc(100vh - ' + (headerHeight + keyboardHeight) + 'px);'"
        v-if="conversationType === 'system'"
      >
        <MessageSystem :data="messages" :types="types" />
      </view>
    </view>
  </PageContainer>
</template>
<script lang="ts">
  import PageContainer from '@/components/PageContainer/index.vue';
  import {
    defineComponent,
    reactive,
    toRefs,
    ref,
    computed,
    nextTick,
    watch,
    onMounted,
    provide,
    unref,
  } from 'vue';
  import { onLoad, navigateTo } from '@/router';
  import { onShow, onUnload } from '@dcloudio/uni-app';

  // 消息元素组件
  import MessageBubble from './components/message-elements/message-bubble.vue';
  import MessageText from './components/message-elements/message-text.vue';
  import MessageImage from './components/message-elements/message-image.vue';
  import MessageVideo from './components/message-elements/message-video.vue';
  import MessageAudio from './components/message-elements/message-audio.vue';
  import MessageFace from './components/message-elements/message-face.vue';
  import MessageCustom from './components/message-elements/message-custom.vue';
  import MessageTip from './components/message-elements/message-tip.vue';
  import MessageRevoked from './components/message-elements/message-revoked.vue';
  import MessageSystem from './components/message-elements/message-system.vue';
  // 底部消息发送组件
  import TUIChatInput from './components/message-input/index.vue';

  import Header from '@/components/Header/index.vue';
  import { useImStoreWithOut } from '@/store/modules/im';
  import tim from '../utils';
  import { caculateTimeago } from '../utils/date';

  import {
    handleName,
    handleTextMessageShowContext,
    handleImageMessageShowContext,
    handleVideoMessageShowContext,
    handleAudioMessageShowContext,
    handleFileMessageShowContext,
    handleFaceMessageShowContext,
    handleLocationMessageShowContext,
    handleMergerMessageShowContext,
    handleTipMessageShowContext,
    handleCustomMessageShowContext,
  } from '../utils/untis';

  export default defineComponent({
    name: 'TUIChat',
    components: {
      MessageText,
      MessageImage,
      MessageVideo,
      MessageAudio,
      MessageFace,
      MessageCustom,
      MessageBubble,
      MessageTip,
      MessageRevoked,
      MessageSystem,
      TUIChatInput,
      Header,
      PageContainer
    },

    setup(props) {
      const SysInfo = uni.getWindowInfo();
      const statusBarHeight = ref<number>(SysInfo.statusBarHeight as number);
      const conHeight = ref<number>(44);
      // #ifdef MP-WEIXIN
      let { height, top } = uni.getMenuButtonBoundingClientRect();
      conHeight.value = height + (top - statusBarHeight.value) * 2;
      // #endif
      const useIm = useImStoreWithOut();

      const left: number | null = 0;
      const right: number | null = 0;
      const defaultDialogPosition = {
        top: -70,
        left,
        right,
      };

      const data = reactive({
        headerHeight: ref<number>(statusBarHeight.value + conHeight.value), // 头部导航高度
        headerTitle: '',
        scrollY: true,
        messageList: computed(() => useIm.messageList),
        conversation: computed(() => useIm.conversation),
        triggered: false,
        oldScrollTop: 0,
        scrollTop: 0,
        text: '',
        types: tim.$TIM.TYPES,
        forwardStatus: false,
        imageFlag: false,
        isCompleted: false, // 是否加载完毕
        oldMessageTime: 0,
        dialogPosition: defaultDialogPosition,
        keyboardHeight: 0, // 软键盘高度
      });

      const noScrollBottom = ref(false);
      const isPlayVideoChange = (isPlay: boolean) => {
        noScrollBottom.value = isPlay;
      };
      provide('isPlayVideo', isPlayVideoChange);

      // 判断当前会话类型：无/系统会话/正常C2C、群聊
      const conversationType = computed(() => {
        const conversation: any = data.conversation;
        if (!conversation?.conversationID) {
          return '';
        }
        if (conversation?.type === tim.$TIM.TYPES.CONV_SYSTEM) {
          return 'system';
        }
        return 'chat';
      });

      // 不展示已删除消息
      const messages = computed(() => {
        if (data.messageList.length > 0) {
          data.oldMessageTime = data.messageList[0].time;
          return data.messageList.filter((item: any) => {
            return !item.isDeleted;
          });
        }
        return [];
      });

      // 获取页面参数
      const conversationID = ref<string>('');
      onLoad<'TUIChat'>(async (op: any) => {
        console.log(op, '页面入参');
        await tim.imLogin();
        conversationID.value = op.conversationID || op.id;

        useIm.isSDKReady ? getData() : tim.$TUIKit.on(tim.$TIM.EVENT.SDK_READY, getData);
        // 软键盘高度监听
        uni.onKeyboardHeightChange((res) => {
          data.keyboardHeight = res.height || 0;
        });
      });
      onUnload(() => {
        // 监听软键盘卸载
        uni.offKeyboardHeightChange();
      });
      onShow(() => {
        if (data.conversation && handleName(data.conversation) !== data.headerTitle) {
          data.headerTitle = handleName(data.conversation);
        }
        handleScrollBottom();
      });

      // 获取聊天对象 && 历史消息
      const getData = async function () {
        try {
          if (unref(conversationID)?.indexOf(tim.$TIM.TYPES.CONV_GROUP) !== -1) {
            // 群聊基础信息,此写法避免后端静默建群
            let groupID = unref(conversationID)?.replace(tim.$TIM.TYPES.CONV_GROUP, '');
            let res = await tim.$TUIKit.getGroupProfile({ groupID });
            useIm.setConversationItem({...useIm.conversation, ...{
              conversationID: unref(conversationID),
              type: tim.$TIM.TYPES.CONV_GROUP,
              groupProfile: res.data.group
            }})
          } else {
            let res = await tim.$TUIKit.getConversationList([unref(conversationID)]);
            if (!res.data?.conversationList || !res.data?.conversationList.length) {
              console.error('未查询到该会话');
            } else {
              useIm.setConversationItem(res.data?.conversationList[0] ?? [])
            }
          }

          // 清除未读消息
          tim.setMessageRead(unref(conversationID));
          // 获取历史消息
          tim.updateStore();
          // 获取标题
          data.headerTitle = handleName(data.conversation);
        } catch (error) {
          console.error(error);
        }
      };

      // 监听数据渲染，展示最新一条消息
      watch(messages, (newVal: any, oldVal: any) => {
        nextTick(() => {
          data.oldMessageTime = messages.value.length ? messages.value[0].time : 0;
          handleShowTime();
          if (newVal.length && !oldVal.length) {
            // 初次进入
            handleScrollBottom();
          } else if (newVal.length !== oldVal.length) {
            // 接收新消息或者发送新消息
            const newMsgLastId = newVal[newVal.length - 1]?.ID ?? undefined;
            const oldMsgLastId = oldVal[oldVal.length - 1]?.ID ?? undefined;
            if (newMsgLastId !== oldMsgLastId) {
              handleScrollBottom();
            }
          }
        });
      });

      onMounted(() => {
        handleShowTime();
        // // 监听回退，已读上报
        uni.addInterceptor('navigateBack', {
          success() {
            // 小程序无效 官网链接：https://uniapp.dcloud.io/api/interceptor.html
            data.conversation.conversationID &&
              tim.setMessageRead(data.conversation.conversationID);
          },
        });
      });

      const handleGetProfile = () => {
        navigateTo({ name: 'TUIGroup' });
      };

      // 显示聊天时间段
      const handleShowTime = () => {
        data.oldMessageTime = 0;
        if (messages.value) {
          Array.from(messages.value).forEach((item) => {
            if (item.time - data.oldMessageTime > 5 * 60) {
              data.oldMessageTime = item.time;
              item.showTime = true;
            } else {
              item.showTime = false;
            }
          });
        }
      };

      // 设置滚动条到底部
      const handleScrollBottom = () => {
        if (unref(noScrollBottom)) return;
        data.scrollTop = data.oldScrollTop;
        uni
          .createSelectorQuery()
          .select('.TUI-message-list')
          .boundingClientRect((res: any) => {
            nextTick(() => {
              data.scrollTop = res?.height ?? 0;
            });
          })
          .exec();
      };

      // 滚动条滚动
      const handleScroll = (e: any) => {
        data.oldScrollTop = e.detail.scrollTop;
      };

      // 输入框失焦,解决ios软键盘顶上输入框无法降下bug
      const inputBlur = (e: any) => {
        data.scrollY = false;
        setTimeout(() => {
          data.scrollY = true;
        }, 500);
      };

      // 下拉加载更多
      const handleRefresher = () => {
        data.triggered = true;
        if (!data.isCompleted) {
          tim.getHistoryMessageList().then((res: any) => {
            data.triggered = false;
            data.isCompleted = res.isCompleted;
          });
        }
        setTimeout(() => {
          data.triggered = false;
        }, 500);
      };

      // 处理需要合并的数据
      const handleSend = (emo: any) => {
        data.text += emo.name;
      };

      // 发送消息
      const handleSendTextMessage = (e: any) => {
        if (data.text.trimEnd()) {
          tim.sendTextMessage(JSON.parse(JSON.stringify(data.text)));
        }
        data.text = ' ';
      };

      // 滑动触发时，失焦收起键盘
      const handleTouchStart = () => {
        uni.hideKeyboard();
      };
      // 重新编辑
      const handleEdit = (item: any) => {
        data.text = item.payload.text;
      };

      return {
        ...toRefs(data),
        conversationType,
        messages,
        handleShowTime,
        handleTouchStart,
        handleRefresher,
        handleScroll,
        handleScrollBottom,
        handleSendTextMessage,
        handleEdit,
        handleTextMessageShowContext,
        handleImageMessageShowContext,
        handleVideoMessageShowContext,
        handleAudioMessageShowContext,
        handleFileMessageShowContext,
        handleFaceMessageShowContext,
        handleLocationMessageShowContext,
        handleMergerMessageShowContext,
        handleTipMessageShowContext,
        handleCustomMessageShowContext,
        handleSend,
        caculateTimeago,
        handleGetProfile,
        inputBlur,
      };
    },
  });
</script>
<style lang="scss" scoped>
  @import '../styles/TUIChat.scss';
</style>
